package cg.cmm.alioss.utils;

import cg.cmm.alioss.config.OssConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class FileUtils {

    private static final String FILE_TYPE_DELIMITER = ".";
    private static final int MIN_FILE_SIZE = 0;
    private static final String NULL_PARAM = "";

    // 阿里云OSS配置
    private static final OssConfig ossConfig = new OssConfig();

    // 文件类型到MIME类型的映射
    private static final Map<String, String> suffixMapToDocumentMimeType;

    // 文件类型到最大文件大小的映射
    private static final Map<String, Long> suffixMapToDocumentSize;

    static {
        Map<String, String> tempSuffixMapToDocumentMimeType = new HashMap<>();
        tempSuffixMapToDocumentMimeType.put("doc", "application/msword");
        tempSuffixMapToDocumentMimeType.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        tempSuffixMapToDocumentMimeType.put("csv", "text/csv");
        tempSuffixMapToDocumentMimeType.put("xls", "application/vnd.ms-excel");
        tempSuffixMapToDocumentMimeType.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        tempSuffixMapToDocumentMimeType.put("ppt", "application/vnd.ms-powerpoint");
        tempSuffixMapToDocumentMimeType.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
        tempSuffixMapToDocumentMimeType.put("pdf", "application/pdf");
        tempSuffixMapToDocumentMimeType.put("xml", "application/xml");
        tempSuffixMapToDocumentMimeType.put("jpg", "image/jpeg");
        tempSuffixMapToDocumentMimeType.put("jpeg", "image/jpeg");
        tempSuffixMapToDocumentMimeType.put("png", "image/png");
        tempSuffixMapToDocumentMimeType.put("zip", "application/zip");
        tempSuffixMapToDocumentMimeType.put("rar", "application/x-rar-compressed");
        tempSuffixMapToDocumentMimeType.put("wps", "application/msword");
        tempSuffixMapToDocumentMimeType.put("mp3", "audio/mpeg");
        tempSuffixMapToDocumentMimeType.put("mp4", "video/mp4");
        tempSuffixMapToDocumentMimeType.put("mov", "video/quicktime");
        tempSuffixMapToDocumentMimeType.put("avi", "video/x-msvideo");
        tempSuffixMapToDocumentMimeType.put("txt", "text/plain");
        tempSuffixMapToDocumentMimeType.put("exf", "text/plain,application/xml");
        tempSuffixMapToDocumentMimeType.put("asc", "application/pgp,application/pgp-encrypted,application/pgp-keys,application/pgp-signature,text/plain");
        tempSuffixMapToDocumentMimeType.put("wmv", "audio/x-ms-wmv,video/x-ms-wmv");
        tempSuffixMapToDocumentMimeType.put("gz", "application/x-gzip,application/gzip");
        tempSuffixMapToDocumentMimeType.put("xlsm", "application/vnd.ms-excel.sheet.macroenabled.12");
        tempSuffixMapToDocumentMimeType.put("m4a", "audio/mp4");
        tempSuffixMapToDocumentMimeType.put("opus", "audio/opus");
        tempSuffixMapToDocumentMimeType.put("flac", "audio/x-flac");
        tempSuffixMapToDocumentMimeType.put("webm", "video/webm");
        tempSuffixMapToDocumentMimeType.put("weba", "audio/webm");
        tempSuffixMapToDocumentMimeType.put("wav", "audio/vnd.wave,audio/wav");
        tempSuffixMapToDocumentMimeType.put("ogg", "audio/vorbis,application/ogg");
        tempSuffixMapToDocumentMimeType.put("oga", "application/ogg,audio/ogg,video/ogg");
        tempSuffixMapToDocumentMimeType.put("mid", "audio/midi");
        tempSuffixMapToDocumentMimeType.put("aiff", "audio/aiff");
        tempSuffixMapToDocumentMimeType.put("wma", "audio/x-ms-wma");
        tempSuffixMapToDocumentMimeType.put("au", "audio/basic");
        tempSuffixMapToDocumentMimeType.put("gif", "image/gif");
        tempSuffixMapToDocumentMimeType.put("bmp", "image/bmp,text/plain,image/jpeg");
        tempSuffixMapToDocumentMimeType.put("jfif", "image/jpeg,image/jp2");
        tempSuffixMapToDocumentMimeType.put("pjp", "image/jpeg,image/jp2");
        tempSuffixMapToDocumentMimeType.put("pjpeg", "image/jpeg");
        tempSuffixMapToDocumentMimeType.put("smr-f", "application/octet-stream");
        tempSuffixMapToDocumentMimeType.put("7z", "application/x-7z-compressed");
        tempSuffixMapToDocumentMimeType.put("tar", "application/x-tar,application/x-gtar");
        tempSuffixMapToDocumentMimeType.put("lz4", "application/x-lz4");
        tempSuffixMapToDocumentMimeType.put("rtf", "application/rtf");
        tempSuffixMapToDocumentMimeType.put("svg", "image/svg+xml");
        tempSuffixMapToDocumentMimeType.put("3gp", "video/3gpp");
        tempSuffixMapToDocumentMimeType.put("flv", "video/x-flv");
        tempSuffixMapToDocumentMimeType.put("mkv", "video/x-matroska");

        suffixMapToDocumentMimeType = Collections.unmodifiableMap(tempSuffixMapToDocumentMimeType);

        Map<String, Long> tempSuffixMapToDocumentSize = new HashMap<>();
        tempSuffixMapToDocumentSize.put("doc", 30 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("docx", 30 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("csv", 30 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("xls", 30 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("xlsx", 30 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("ppt", 30 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("pptx", 30 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("pdf", 30 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("jpg", 5 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("jpeg", 5 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("png", 5 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("zip", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("rar", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("wps", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("mov", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("avi", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("mp3", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("mp4", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("txt", 2 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("exf", 2 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("asc", 2 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("wmv", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("gz", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("xlsm", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("m4a", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("opus", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("flac", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("webm", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("weba", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("wav", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("ogg", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("oga", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("mid", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("aiff", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("wma", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("au", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("gif", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("bmp", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("jfif", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("pjp", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("pjpeg", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("smr-f", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("7z", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("tar", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("lz4", 50 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("rtf", 20 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("svg", 20 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("3gp", 20 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("flv", 20 * 1024 * 1024L);
        tempSuffixMapToDocumentSize.put("mkv", 20 * 1024 * 1024L);

        suffixMapToDocumentSize = Collections.unmodifiableMap(tempSuffixMapToDocumentSize);
    }

    // 其他方法保持不变...

    public static File multipartFileToFile(MultipartFile file) {
        if (NULL_PARAM.equals(file) || file.getSize() <= MIN_FILE_SIZE) {
            return null;
        }
        try (InputStream ins = file.getInputStream()) {
            File toFile = new File(file.getOriginalFilename());
            inputStreamToFile(ins, toFile);
            return toFile;
        } catch (IOException e) {
            log.error("multipartFileToFile IOException: {}", e.getMessage());
        }
        return null;
    }

    public static void inputStreamToFile(InputStream ins, File file) {
        try (OutputStream os = Files.newOutputStream(Paths.get(file.getAbsolutePath()))) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            log.error("inputStreamToFile Exception: {}", e.getMessage());
        }
    }

    public static String processFilename(String originalFileName) {
        String[] nameParts;
        if (originalFileName.contains("\\")) {
            nameParts = originalFileName.split("\\\\");
        } else {
            nameParts = originalFileName.split("/");
        }
        return nameParts[nameParts.length - 1];
    }

    public static String getSuffix(String docName) {
        if (docName == null) {
            return "";
        }
        int lastIndexOfFileType = docName.lastIndexOf(FILE_TYPE_DELIMITER);
        return docName.substring(lastIndexOfFileType + 1).toLowerCase(Locale.CHINA);
    }

    public static String validFileName(String originalFilename) {
        String regEx = "[`~!@#$%^&*()+=|{}':;',/[//]<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(originalFilename);
        return m.replaceAll("").replace(" ", "").trim();
    }

    public static String getDocumentMimeTypeByDocName(String docName) {
        String suffix = getSuffix(docName);
        return getDocumentMimeTypeBySuffix(suffix);
    }

    public static Long getDocumentSizeByDocName(String docName) {
        String suffix = getSuffix(docName);
        Long suffixSize = suffixMapToDocumentSize.get(suffix);
        if (ObjectUtils.isEmpty(suffixMapToDocumentSize)) {
            return 100 * 1024 * 1024L;
        }
        return suffixSize;
    }

    private static String getDocumentMimeTypeBySuffix(String suffix) {
        return suffixMapToDocumentMimeType.get(suffix);
    }

    public static void deleteTempFile(File file) {
        if (file != null) {
            File del = new File(file.toURI());
            del.delete();
        }
    }
}
